<%# The license inside this block applies to this file.
  # Copyright 2017 Google Inc.
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
-%>
<% if property.custom_expand -%>
<%= lines(compile_template(pwd + '/' + property.custom_expand,
                           prefix: prefix,
                           property: property,
                           object: object,
                           pwd: pwd)) -%>
<% else -%>

<%# Generate expanders for Maps %>
<%   if property.is_a?(Api::Type::Map) -%>
func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d TerraformResourceData, config *Config) (map[string]interface{}, error) {
  if v == nil {
    return map[string]interface{}{}, nil
  }
  m := make(map[string]interface{})
  for _, raw := range v.(*schema.Set).List() {
    original := raw.(map[string]interface{})
    transformed := make(map[string]interface{})

<%     property.nested_properties.each do |prop| -%>
<%       next if prop.name == property.key_name -%>
    transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(original["<%= Google::StringUtils.underscore(prop.name) -%>"], d, config)
    if err != nil {
      return nil, err
    <%       if prop.send_empty_value -%>
    } else {
      transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
    <%       else -%>
    } else if val := reflect.ValueOf(transformed<%= titlelize_property(prop) -%>); val.IsValid() && !isEmptyValue(val) {
      transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
    <%       end -%>
    }

<%     end -%>

    transformed<%= property.key_name.camelize(:upper) -%>, err := <%= property.key_expander -%>(original["<%= Google::StringUtils.underscore(property.key_name) -%>"], d, config)
    if err != nil {
      return nil, err
    }
    m[transformed<%= property.key_name.camelize(:upper) -%>] = transformed
  }
  return m, nil
}
<%# End expanders for Maps %>

<%# Generate expanders for KeyValuePairs %>
<%   elsif property.is_a?(Api::Type::KeyValuePairs) -%>
func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
  if v == nil {
    return map[string]string{}, nil
  }
  m := make(map[string]string)
  for k, val := range v.(map[string]interface{}) {
    m[k] = val.(string)
  }
  return m, nil
}

<%# Generate expanders for flattened objects %>
<%   elsif property.flatten_object -%>
func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
  transformed := make(map[string]interface{})
<%     property.nested_properties.each do |prop| -%>
  <% schemaPrefix = prop.flatten_object ? "nil" : "d.Get( \"#{prop.name.underscore}\" )" -%>
  transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(<%= schemaPrefix -%>, d, config)
  if err != nil {
    return nil, err
<%       if prop.send_empty_value -%>
  } else {
    transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
<%       else -%>
  } else if val := reflect.ValueOf(transformed<%= titlelize_property(prop) -%>); val.IsValid() && !isEmptyValue(val) {
    transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
<%       end -%>
  }

<%     end -%>
  return transformed, nil
}

<%# Generate expanders for everything else %>
<%   elsif tf_types.include?(property.class) -%>
func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
<%     if property.is_set -%>
  v = v.(*schema.Set).List()
<%     end -%>
<%     if property.nested_properties? -%>
  l := v.([]interface{})
<%       if property.is_a?(Api::Type::Array) -%>
  req := make([]interface{}, 0, len(l))
  for _, raw := range l {
    if raw == nil {
      continue
    }
<%       else -%>
<%         if property.allow_empty_object -%>
  if len(l) == 0 {
    return nil, nil
  }

  if l[0] == nil {
    transformed := make(map[string]interface{})
    return transformed, nil
  }
<%       else -%>
  if len(l) == 0 || l[0] == nil {
    return nil, nil
  }
<%         end -%>
  raw := l[0]
<%       end -%>
    original := raw.(map[string]interface{})
    transformed := make(map[string]interface{})

<%       property.nested_properties.each do |prop| -%>
      transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(original["<%= prop.name.underscore -%>"], d, config)
      if err != nil {
        return nil, err
<%         unless prop.send_empty_value -%>
      } else if val := reflect.ValueOf(transformed<%= titlelize_property(prop) -%>); val.IsValid() && !isEmptyValue(val) {
        transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
<%         else -%>
      } else {
        transformed["<%= prop.api_name -%>"] = transformed<%= titlelize_property(prop) -%>
<%         end -%>
      }

<%       end -%>
<%       if property.is_a?(Api::Type::Array) -%>
    req = append(req, transformed)
  }
  return req, nil
<%       else -%>
  return transformed, nil
<%       end -%>
}


<%     elsif property.is_a?(Api::Type::Array) && property.item_type.is_a?(Api::Type::ResourceRef) -%>
  l := v.([]interface{})
  req := make([]interface{}, 0, len(l))
  for _, raw := range l {
    if raw == nil {
      return nil, fmt.Errorf("Invalid value for <%= property.name.underscore -%>: nil")
    }
    f, err := <%= build_expand_resource_ref('raw.(string)', property.item_type, pwd) %>
    if err != nil {
      return nil, fmt.Errorf("Invalid value for <%= property.name.underscore -%>: %s", err)
    }
    req = append(req, f.RelativeLink())
  }
  return req, nil
}
<%     else -%>
<%       if property.is_a?(Api::Type::ResourceRef) -%>
  f, err := <%= build_expand_resource_ref('v.(string)', property, pwd) %>
  if err != nil {
    return nil, fmt.Errorf("Invalid value for <%= property.name.underscore -%>: %s", err)
  }
  return f.RelativeLink(), nil
}
<%       else -%>
  return v, nil
}
<%       end -%>
<%     end # nested_properties, array of resourcerefs, else -%>
<%   else -%>
  // TODO: Property '<%= property.name -%>' of type <%= property.class -%> is not supported
}
<%   end # tf_types.include?(property.class) -%>

<% if property.nested_properties? -%>
<%   property.nested_properties.each do |prop| -%>
<%# Map is a map from {key -> object} in the API, but Terraform can't represent that
so we treat the key as a property of the object in Terraform schema. %>
<%=    lines(build_expand_method(prefix + titlelize_property(property), prop, object, pwd), 1) -%>
<%   end -%>
<% end -%>

<% end # custom_code check -%>
